

/**CFile****************************************************************
 
  FileName    [app.c] 

  SystemName  []

  PackageName []
  
  Synopsis    [基于ABC的近似计算函数编写]

  Author      []
   
  Affiliation []

  Date        [2021.7.13]

***********************************************************************/
#include <iostream>
using namespace std;
#include <stdio.h>
#include <time.h>
#include "base/abc/abc.h"
#include "app.h"
#include "aig/aig/aig.h"
#include "simulatorPro.h"
#include "opt.h"
#include "delay.h"
#include <vector>
#include <map>
#include <string.h>

extern Abc_Ntk_t *App_GetBestDely(Abc_Ntk_t *pNtk, double bound)
{
    DelyNode delaynode;
 //   pNtk = GetBestDelayNtk(pNtk, delaynode, bound);
    SaveMessage(pNtk, delaynode);
    setiTemp(pNtk);
    CalWeight(pNtk, delaynode);
    test(pNtk, delaynode);
    return pNtk;
}

void SaveMessage(Abc_Ntk_t *pNtk, DelyNode &delaynode)
{
    Abc_Obj_t *pNode = NULL,*ppo = NULL;
    int i = 0;
    //保存当前电路与PO相连节点名称
     Abc_NtkForEachPo(pNtk,ppo,i)
     {
         pNode = Abc_ObjFanin0(ppo);
         delaynode.topid.push_back(pNode->Id);
       //  cout << "pass" << endl;
         getCriticalPath(pNode, delaynode);
     }
    //根据PO相连节点寻找到所有关键路径
    for (i = 0; i < delaynode.topid.size(); i++)
    {
        delaynode.pathcone.push_back(delaynode.topid[i]);
        getCriticalPath(Abc_NtkObj(pNtk, delaynode.topid[i]), delaynode);
    }
}

void getCriticalPath(Abc_Obj_t *pNode, DelyNode &delaynode)
{
    Abc_Obj_t *pNode1 = NULL, *pNode2 = NULL;
    if (pNode->Level == 0)
    {
        return;
    }
    if (Abc_ObjFanin0(pNode)->Level != Abc_ObjFanin1(pNode)->Level)
    {
        pNode = Abc_ObjFanin0(pNode)->Level > Abc_ObjFanin1(pNode)->Level ? Abc_ObjFanin0(pNode) : Abc_ObjFanin1(pNode);
        SaveNoDuplicationId(pNode, delaynode);
        getCriticalPath(pNode, delaynode);
    }
    else
    {
        pNode1 = Abc_ObjFanin0(pNode);
        pNode2 = Abc_ObjFanin1(pNode);
        SaveNoDuplicationId(pNode1, delaynode);
        getCriticalPath(pNode1, delaynode);
        SaveNoDuplicationId(pNode2, delaynode);
        getCriticalPath(pNode2, delaynode);
    }
}

void SaveNoDuplicationId(Abc_Obj_t *pNode, DelyNode &delaynode)
{
    int idIsExist = 0;
    for (int i = 0; i < delaynode.pathcone.size(); i++)
    {
        if (delaynode.pathcone[i] == pNode->Id)
        {
            idIsExist = 1;
            pNode->dTemp++;
        }
    }
    if (idIsExist == 0)
    {
        delaynode.pathcone.push_back(pNode->Id);
    }
    else
    {
        idIsExist = 0;
    }
}

void setiTemp(Abc_Ntk_t *pNtk)
{
    Abc_Obj_t *pNode;
    int i = 0;
    Abc_NtkForEachObj(pNtk, pNode, i)
    {
        pNode->dTemp = 1;
    }
}

Abc_Ntk_t *GetBestDelayNtk(Abc_Ntk_t *pNtk, DelyNode &delaynode, double bound)
{
    Abc_Ntk_t *ptempNtk = NULL, *pNtk_org = NULL;
    Abc_Obj_t *pNode = NULL;
    int fanoutnum = 0, i = 0;
    double error = 0;
    ptempNtk = Abc_NtkDup(pNtk);
    pNtk_org = Abc_NtkDup(pNtk);
    Abc_NtkPrintStats(pNtk_org, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
    pNtk_org = NtktoAig(pNtk_org);
    while (error < bound)
    {
        pNtk = Optimaize_resyn2(pNtk);
        random_device rd;
        unsigned seed = static_cast<unsigned>(rd());
        cout << "seed :" << seed << endl;
        //清除上一次保存的电路节点信息
        setiTemp(pNtk);
        delaynode.topid.clear();
        delaynode.pathcone.clear();
        SaveMessage(pNtk, delaynode);
        Abc_NtkDelete(ptempNtk);
        ptempNtk = Abc_NtkDup(pNtk);
        Abc_NtkPrintStats(pNtk, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
        cout << "level: " << Abc_NtkLevel(pNtk) << endl;
        for (i = 0; i < delaynode.pathcone.size(); i++)
        {
            if (Abc_ObjLevel(Abc_NtkObj(pNtk, delaynode.pathcone[i])) == 1)
            {
                pNode = Abc_NtkObj(pNtk, delaynode.pathcone[i]);
                fanoutnum = pNode->vFanouts.nSize;
                //常量替换
                DelayConstreplace(pNtk, pNode, fanoutnum);
            }
        }
        pNtk = NtktoAig(pNtk);
        error = MeasureER(pNtk, pNtk_org, 102400, seed, false);
        pNtk = NtkStrash(pNtk);
        cout << "errorrate: " << error << endl;
        if (error > bound)
        {
            pNtk = ptempNtk;
            break;
        }
    }
    return pNtk;
}

void CalWeight(Abc_Ntk_t *pNtk, DelyNode &delaynode)
{
    Abc_Obj_t *pNode = NULL;
    //权重值是由该节点在关键路径中遍历累计次数与其所在层级相除所得到的，使用multimap容器进行存储
    for (int i = 0; i < delaynode.pathcone.size(); i++)
    {
          pNode = Abc_NtkObj(pNtk, delaynode.pathcone[i]);
          if(Abc_ObjIsPi(pNode)!=1)
          delaynode.weight.insert(pair<double, int>(((pNode->dTemp*1000) / Abc_ObjLevel(pNode)), Abc_NtkObj(pNtk, delaynode.pathcone[i])->Id));
    }
    //将所得到的排好序的id保存到vector容器中
    for(multimap<double,int>::iterator it = delaynode.weight.begin();it != delaynode.weight.end();it++)
    {
        delaynode.weightcone.push_back((*it).second);
    }


}

void DelayConstreplace(Abc_Ntk_t *pNtk, Abc_Obj_t *pNode, int fanoutnum)
{
    Abc_Obj_t *pConst1 = NULL, *pConst0 = NULL;
    Abc_Obj_t *pRootfanout = NULL;
    pConst1 = Abc_AigConst1(pNtk);
    pConst0 = Abc_ObjNot(pConst1);
    if (fanoutnum > 100)
        return;
    // pRootfanout =Abc_ObjFanout(pNode,(rand()%fanoutnum));
    pRootfanout = Abc_ObjFanout(pNode, 0);
    if (Abc_ObjFanin0(pRootfanout) == pNode)
    {
        if (pRootfanout->fCompl0 == 1)
        {
            Abc_ObjPatchFanin(pRootfanout, pNode, pConst1);
        }
        else
        {
            Abc_ObjPatchFanin(pRootfanout, pNode, pConst0);
        }
    }
    if (Abc_ObjFanin1(pRootfanout) == pNode)
    {
        if (pRootfanout->fCompl1 == 1)
        {
            Abc_ObjPatchFanin(pRootfanout, pNode, pConst1);
        }
        else
        {
            Abc_ObjPatchFanin(pRootfanout, pNode, pConst0);
        }
    }
}

void test(Abc_Ntk_t *pNtk, DelyNode &delaynode)
{
    int i;
    vector<int> temppath;
    cout << "与PO相连节点id: ";
    for (i = 0; i < delaynode.topid.size(); i++)
    {
        cout << delaynode.topid[i] << " ";
    }
    cout << endl;
    cout << "-----------所有关键路径节点总集合------------" << endl;
    for (i = 0; i < delaynode.pathcone.size(); i++)
    {
        cout << delaynode.pathcone[i] << " ";
    }
    cout << endl;
/*     cout << "---------关键路径途径次数大于0的节点有---------" << endl;
    for (i = 0; i < delaynode.pathcone.size(); i++)
    {
        if (Abc_NtkObj(pNtk, delaynode.pathcone[i])->dTemp > 1)
        {
            cout << "Id: " << Abc_NtkObj(pNtk, delaynode.pathcone[i])->Id << " 次数 " << Abc_NtkObj(pNtk, delaynode.pathcone[i])->dTemp << " ";
        }
    }
    cout << endl; */
    //测试打印模块
    cout << "-----------按照权重从大到小一次排序------------" << endl;
    for(i = 0; i < delaynode.weightcone.size(); i++)
    {
        cout << delaynode.weightcone[i] << " ";
    }
    cout << endl;
}